<template>
    <div :class="['cvu-table', `cvu-table-${theme}`]">
        <Table 
            ref="table"
            :columns="columns" 
            :data="data"
            :stripe="stripe"
            :border="border"
            :show-header="showHeader"
            :width="width"
            :height="height"
            :max-height="maxHeight"
            :loading="loading"
            :disabled-hover="disabledHover"
            :highlight-row="highlightRow"
            :row-class-name="rowClassName"
            :size="size"
            :no-data-text="noDataText"
            :no-filtered-data-text="noFilteredDataText"
            :draggable="draggable"
            :tooltip-theme="tooltipTheme"
            :tooltip-max-width="tooltipMaxWidth"
            :row-key="rowKey"
            :span-method="spanMethod"
            :show-summary="showSummary"
            :sum-text="sumText"
            :summary-method="summaryMethod"
            :indent-size="indentSize"
            :load-data="loadData"
            :update-show-children="updateShowChildren"
            :context-menu="contextMenu"
            :show-context-menu="showContextMenu"
            :fixed-shadow="fixedShadow"
            @on-current-change="handleCurrentChange"
            @on-select="handleSelect"
            @on-select-cancel="heandleSelectCancel"
            @on-select-all="handleSelectAll"
            @on-select-all-cancel="handleSelectAllCancel"
            @on-selection-change="handleSelectionChange"
            @on-sort-change="handleSortChange"
            @on-filter-change="handleFilterChange"
            @on-row-click="handleRowClick"
            @on-row-dblclick="handleRowDblclick"
            @on-cell-click="handleCellClick"
            @on-expand="handleExpand"
            @on-drag-drop="handleDragDrop"
            @on-column-width-resize="handleColumnWidthResize"
            @on-contextmenu="handleContextmenu"
            @on-expand-tree="handleExpandTree"
        >
            <template slot="header" v-if="$slots.header">
                <slot name="header" />
            </template>
            <template v-for="(column, index) in columns"
                :slot="column.slot ? column.slot : ''" 
                slot-scope="params" 
            >
                <slot :name="column.slot ? column.slot : ''" v-bind="params" ></slot>
            </template>
            <template slot="loading" v-if="$slots.loading">
                <slot name="loading" />
            </template>
            <template slot="contextMenu" v-if="$slots.contextMenu">
                <slot name="contextMenu" />
            </template>
            <template slot="footer" v-if="$slots.footer">
                <slot name="footer" />
            </template>
        </Table>
    </div>
</template>
<script>
import common from '../../../until/common'
export default {
    name: 'cvu-table',
    props: {
        // 列配置
        columns: {
            type: Array,
            default: () => {}
        },
        // 表格数据
        data: {
            type: Array,
            default: () => {}
        },
        // 风格，可选值row：横向表格 col：纵向表格
        theme: {
            type: String,
            validator (value) {
                return common.oneOf(value, ['default', 'row', 'col']);
            },
            default: 'default'
        },
        // 是否显示间隔斑马纹
        stripe: {
            type: Boolean,
            default: false
        },
        // 是否显示纵向边框
        border: {
            type: Boolean,
            default: false
        },
        // 是否显示表头
        showHeader: {
            type: Boolean,
            default: true
        },
        // 表格宽度，单位 px
        width: [Number, String],
        // 表格高度，单位 px，设置后，如果表格内容大于此值，会固定表头
        height: [Number, String],
        // 表格最大高度，单位 px，设置后，如果表格内容大于此值，会固定表头
        maxHeight: [Number, String],
        // 表格是否加载中
        loading: {
            type: Boolean,
            default: false
        },
        // 禁用鼠标悬停时的高亮
        disabledHover: {
            type: Boolean,
            default: false
        },
        // 是否支持高亮选中的行，即单选
        highlightRow: {
            type: Boolean,
            default: false
        },
        // 行的 className 的回调方法，传入参数：row：当前行数据  index：当前行的索引
        rowClassName: Function,
        // 表格尺寸，可选值为 large、small、default 或者不填
        size: String,
        // 数据为空时显示的提示内容
        noDataText: {
            type: String,
            default: '暂无数据'
        },
        // 筛选数据为空时显示的提示内容
        noFilteredDataText: {
            type: String,
            default: '暂无筛选结果'
        },
        // 是否开启拖拽调整行顺序，需配合 @on-drag-drop 事件使用
        draggable: {
            type: Boolean,
            default: false
        },
        // 列使用 tooltip 时，配置它的主题，可选值为 dark 或 light
        tooltipTheme: {
            type: String,
            default: 'dark'
        },
        // 列使用 tooltip 时，配置 Tooltip 的最大宽，默认是 300
        tooltipMaxWidth: {
            type: Number,
            default: 300
        },
        // 是否强制使用内置的 row-key，开启后可能会影响性能
        rowKey: [Boolean, String],
        // 合并行或列的计算方法
        spanMethod: Function,
        // 是否在表尾显示合计行
        showSummary: {
            type: Boolean,
            default: false
        },
        // 合计行第一列的文本
        sumText: {
            type: String,
            default: '合计'
        },
        // 自定义的合计计算方法
        summaryMethod: Function,
        // 树形数据缩进宽度，单位 px
        indentSize: {
            type: Number,
            default: 16
        },
        // 异步加载树形数据的方法
        loadData: Function,
        // 展开树形数据时，是否需要更新 _showChildren 字段，使用异步树形数据时建议开启
        updateShowChildren: {
            type: Boolean,
            default: false
        },
        // 当前行点击右键是否会阻止默认行为
        contextMenu: {
            type: Boolean,
            default: false
        },
        // 点击右键弹出菜单，需配合 slot contextMenu 一起使用
        showContextMenu: {
            type: Boolean,
            default: false
        },
        // 列固定时，阴影显示规则，可选值为 auto、show、hide
        fixedShadow: {
            type: String,
            default: 'show'
        }
    },
    methods: {
        // 开启 highlight-row 后有效，当表格的当前行发生变化的时候会触发
        handleCurrentChange(currentRow, oldCurrentRow) {
            this.$emit('on-current-change', currentRow, oldCurrentRow)
        },
        // 在多选模式下有效，选中某一项时触发
        handleSelect(selection, row) {
            this.$emit('on-select', selection, row)
        },
        // 在多选模式下有效，取消选中某一项时触发
        heandleSelectCancel(selection, row) {
            this.$emit('on-select-cancel', selection, row)
        },
        // 在多选模式下有效，点击全选时触发
        handleSelectAll(selection) {
            this.$emit('on-select-all', selection)
        },
        // 在多选模式下有效，点击取消全选时触发
        handleSelectAllCancel(selection) {
            this.$emit('on-select-all-cancel', selection)
        },
        // 在多选模式下有效，只要选中项发生变化时就会触发
        handleSelectionChange(selection) {
            this.$emit('on-selection-change', selection)
        },
        // 排序时有效，当点击排序时触发
        handleSortChange(column, key, order) {
            this.$emit('on-sort-change', column, key, order)
        },
        // 筛选时有效，筛选条件发生变化时触发
        handleFilterChange(column) {
            this.$emit('on-filter-change', column)
        },
        // 单击某一行时触发
        handleRowClick(row, index) {
            this.$emit('on-row-click', row, index)
        },
        // 双击某一行时触发
        handleRowDblclick(row, index) {
            this.$emit('on-row-dblclick', row, index)
        },
        // 点击单元格时触发
        handleCellClick(row, column, data, event) {
            this.$emit('on-cell-click', row, column, data, event)
        },
        // 展开或收起某一行时触发
        handleExpand(row, status) {
            this.$emit('on-expand', row, status)
        },
        // 拖拽排序松开时触发，返回置换的两行数据索引
        handleDragDrop(index1, index2) {
            this.$emit('on-drag-drop', index1, index2)
        },
        // 拖拽调整列宽时触发
        handleColumnWidthResize(newWidth, oldWidth, column, event) {
            this.$emit('on-column-width-resize', newWidth, oldWidth, column, event)
        },
        // 当前行点击右键时触发
        handleContextmenu(row, event, position) {
            this.$emit('on-contextmenu', row, event, position)
        },
        // 展开或收起子数据时触发
        handleExpandTree(rowKey, status) {
            this.$emit('on-expand-tree', rowKey, status)
        },
        /** 将数据导出为 .csv 文件
         * params(Object):
                filename 文件名，默认为 table.csv
                original 是否导出为原始数据，默认为 true
                noHeader 不显示表头，默认为 false
                columns 自定义导出的列数据
                data 自定义导出的行数据
                callback 添加此函数后，不会下载，而是返回数据
                separator 数据分隔符，默认是逗号(,)
                quoted 每项数据是否加引号，默认为 false
                说明：columns 和 data 需同时声明，声明后将导出指定的数据，建议列数据有自定义render时，可以根据需求自定义导出内容
         */
        exportCsv(params = {}) {
            this.$refs.table.exportCsv(params || {})
        },
        // 清除高亮项，仅在开启 highlight-row 时可用
        clearCurrentRow() {
            this.$refs.table.clearCurrentRow()
        },
        // 全选/取消全选
        selectAll(status) {
            this.$refs.table.selectAll(status)
        }
    }
}
</script>
<style lang="scss" scoped>
@import '../../../style/_index.scss';
.cvu-table{
    padding: 4px;
    box-sizing: border-box;
    overflow: hidden;
    /deep/.ivu-table-wrapper{
        width: 100%;
        .ivu-table{
            width: 100%;
            &::before{ display: none; }
            .ivu-table-header thead tr th{
                background: #ceecfd;
            }
            // 间隔斑马纹
            &.ivu-table-stripe .ivu-table-body tr:nth-child(2n) td, 
            &.ivu-table-stripe .ivu-table-fixed-body tr:nth-child(2n) td{
                background: #f9f9f9;
            }
            // 鼠标悬浮
            &.ivu-table-stripe .ivu-table-body tr.ivu-table-row-hover td, 
            &.ivu-table-stripe .ivu-table-fixed-body tr.ivu-table-row-hover td{
                background: #e7f5ff;
            }
            // 带边框表格
            &.ivu-table-border th, 
            &.ivu-table-border td{
                border-right: none;
                position: relative;
                &::before{ content: ''; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background: #dcdee2; transform: scaleY(.8); }
                &::after{ content: ''; position: absolute; right: 0; top: 0; width: 1px; height: 100%; background: #dcdee2; transform: scaleX(.8); }
                &:last-child{
                    &::after{ display: none; }
                }
            }
            .ivu-table-cell{
                padding-left: 10px;
                padding-right: 10px;
            }
        }
    }
    &.cvu-table-col{
        /deep/.ivu-table-wrapper{
            .ivu-table{
                // 间隔斑马纹
                .ivu-table-body tr:nth-child(2n) td, 
                .ivu-table-fixed-body tr:nth-child(2n) td{
                    background: #f9f9f9;
                }
                // 鼠标悬浮
                .ivu-table-body tr.ivu-table-row-hover td, 
                .ivu-table-fixed-body tr.ivu-table-row-hover td{
                    background: #e7f5ff;
                }
            }
        }
    }
    &.cvu-table-row{
        /deep/.ivu-table-wrapper{
            border: 1px solid #dcdee2;
            border-bottom: none;
            border-right: none;
            .ivu-table{
                &::after{ content: ''; width: 1px; height: 100%; position: absolute; top: 0; right: 0; background-color: #dcdee2; z-index: 3; }
                .ivu-table-header{
                    display: none;
                }
                // 带边框表格
                th, td{
                    border-right: none;
                    position: relative;
                    &::before{ content: ''; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background: #dcdee2; transform: scaleY(.8); }
                    &::after{ content: ''; position: absolute; right: 0; top: 0; width: 1px; height: 100%; background: #dcdee2; transform: scaleX(.8); }
                    &:last-child{
                        &::after{ display: none; }
                    }
                }
                tr td{
                    &:nth-child(odd){
                        background:#F8F8F9;
                    }
                    &:nth-child(even){
                        background:#FFFFFF;
                        &:hover{
                            background: #e7f5ff;
                        }
                    }
                }
            }
        }
    }
}
</style>